-- Copyright (c) 2024 Huawei Technologies Co., Ltd.
-- openUBMC is licensed under Mulan PSL v2.
-- You can use this software according to the terms and conditions of the Mulan PSL v2.
-- You may obtain a copy of Mulan PSL v2 at:
--          http://license.coscl.org.cn/MulanPSL2
-- THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
-- EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
-- MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
-- See the Mulan PSL v2 for more details.
local mdb = require 'mc.mdb'
local class = require 'mc.class'
local app_base = require 'mc.client_app_base'
local mdb_service = require 'mc.mdb.mdb_service'
local subscribe_signal = require 'mc.mdb.subscribe_signal'

local get_non_virtual_interface_objects = mdb_service.get_non_virtual_interface_objects
local foreach_non_virtual_interface_objects = mdb_service.foreach_non_virtual_interface_objects

local Certificate = require 'spdm.json_types.Certificate'
local CertificateService = require 'spdm.json_types.CertificateService'
local Hardware = require 'spdm.json_types.Hardware'

---@class spdm_client: BasicClient
local spdm_client = class(app_base.Client)

function spdm_client:GetCertificatesCACertificateObject(path_params)
    return mdb.try_get_object(self:get_bus(),
        path_params and ('/bmc/kepler/Managers/' .. path_params['ManagerId'] .. '/Certificates/' .. path_params['Id']) or
            '/bmc/kepler/Managers/:ManagerId/Certificates/:Id', 'bmc.kepler.CertificateService.Certificate')
end

function spdm_client:GetCertificateObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.CertificateService.Certificate', true,
        {'/bmc/kepler/Managers/:ManagerId/Certificates/:Id'})
end

function spdm_client:ForeachCertificateObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.CertificateService.Certificate', cb, true,
        {'/bmc/kepler/Managers/:ManagerId/Certificates/:Id'})
end

function spdm_client:OnCertificateInterfacesAdded(cb, path_params)
    local path_namespace = path_params and
                               ('/bmc/kepler/Managers/' .. path_params['ManagerId'] .. '/Certificates/' ..
                                   path_params['Id']) or '/bmc/kepler/Managers/:ManagerId/Certificates/:Id'
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), path_namespace, cb,
        'bmc.kepler.CertificateService.Certificate')
end

function spdm_client:OnCertificateInterfacesRemoved(cb, path_params)
    local path_namespace = path_params and
                               ('/bmc/kepler/Managers/' .. path_params['ManagerId'] .. '/Certificates/' ..
                                   path_params['Id']) or '/bmc/kepler/Managers/:ManagerId/Certificates/:Id'
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), path_namespace,
        cb, 'bmc.kepler.CertificateService.Certificate')
end

function spdm_client:GetCertificateServiceCertificateServiceObject()
    return mdb.try_get_object(self:get_bus(), '/bmc/kepler/CertificateService', 'bmc.kepler.CertificateService')
end

function spdm_client:OnCertificateServiceInterfacesAdded(cb)
    local path_namespace = '/bmc/kepler/CertificateService'
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), path_namespace, cb,
        'bmc.kepler.CertificateService')
end

function spdm_client:OnCertificateServiceInterfacesRemoved(cb)
    local path_namespace = '/bmc/kepler/CertificateService'
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), path_namespace,
        cb, 'bmc.kepler.CertificateService')
end

function spdm_client:GetControllerHardwareObject(path_params)
    return mdb.try_get_object(self:get_bus(),
        path_params and
            ('/bmc/kepler/Systems/' .. path_params['SystemId'] .. '/Storage/Controllers/' .. path_params['Id']) or
            '/bmc/kepler/Systems/:SystemId/Storage/Controllers/:Id', 'bmc.kepler.Inventory.Hardware')
end

function spdm_client:GetHardwareObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Inventory.Hardware', true,
        {'/bmc/kepler/Systems/:SystemId/Storage/Controllers/:Id'})
end

function spdm_client:ForeachHardwareObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Inventory.Hardware', cb, true,
        {'/bmc/kepler/Systems/:SystemId/Storage/Controllers/:Id'})
end

function spdm_client:OnHardwareInterfacesAdded(cb, path_params)
    local path_namespace = path_params and
                               ('/bmc/kepler/Systems/' .. path_params['SystemId'] .. '/Storage/Controllers/' ..
                                   path_params['Id']) or '/bmc/kepler/Systems/:SystemId/Storage/Controllers/:Id'
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), path_namespace, cb,
        'bmc.kepler.Inventory.Hardware')
end

function spdm_client:OnHardwareInterfacesRemoved(cb, path_params)
    local path_namespace = path_params and
                               ('/bmc/kepler/Systems/' .. path_params['SystemId'] .. '/Storage/Controllers/' ..
                                   path_params['Id']) or '/bmc/kepler/Systems/:SystemId/Storage/Controllers/:Id'
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), path_namespace,
        cb, 'bmc.kepler.Inventory.Hardware')
end

---@return Certificate.DeleteCRLRsp
function spdm_client:CertificatesCACertificateDeleteCRL(ctx, path_params)
    local obj = self:GetCertificatesCACertificateObject(path_params)

    return Certificate.DeleteCRLRsp.new(obj:DeleteCRL(ctx))
end

function spdm_client:PCertificatesCACertificateDeleteCRL(ctx, path_params)
    return pcall(function()
        local obj = self:GetCertificatesCACertificateObject(path_params)

        return Certificate.DeleteCRLRsp.new(obj:DeleteCRL(ctx))
    end)
end

---@return Certificate.GetCertificateStringRsp
function spdm_client:CertificatesCACertificateGetCertificateString(ctx, path_params)
    local obj = self:GetCertificatesCACertificateObject(path_params)

    return Certificate.GetCertificateStringRsp.new(obj:GetCertificateString(ctx))
end

function spdm_client:PCertificatesCACertificateGetCertificateString(ctx, path_params)
    return pcall(function()
        local obj = self:GetCertificatesCACertificateObject(path_params)

        return Certificate.GetCertificateStringRsp.new(obj:GetCertificateString(ctx))
    end)
end

---@param CertificateUsageType CertificateService.CertificateUsageType
---@return CertificateService.GetCertPathRsp
function spdm_client:CertificateServiceCertificateServiceGetCertPath(ctx, CertificateUsageType)
    local req = CertificateService.GetCertPathReq.new(CertificateUsageType):validate()
    local obj = self:GetCertificateServiceCertificateServiceObject()

    return CertificateService.GetCertPathRsp.new(obj:GetCertPath(ctx, req:unpack(true)))
end

function spdm_client:PCertificateServiceCertificateServiceGetCertPath(ctx, CertificateUsageType)
    return pcall(function()
        local req = CertificateService.GetCertPathReq.new(CertificateUsageType):validate()
        local obj = self:GetCertificateServiceCertificateServiceObject()

        return CertificateService.GetCertPathRsp.new(obj:GetCertPath(ctx, req:unpack(true)))
    end)
end

---@param CertificateUsageType CertificateService.CertificateUsageType
---@param Type string
---@param Content string
---@param Id integer
---@return CertificateService.ImportCertRsp
function spdm_client:CertificateServiceCertificateServiceImportCert(ctx, CertificateUsageType, Type, Content, Id)
    local req = CertificateService.ImportCertReq.new(CertificateUsageType, Type, Content, Id):validate()
    local obj = self:GetCertificateServiceCertificateServiceObject()

    return CertificateService.ImportCertRsp.new(obj:ImportCert(ctx, req:unpack(true)))
end

function spdm_client:PCertificateServiceCertificateServiceImportCert(ctx, CertificateUsageType, Type, Content, Id)
    return pcall(function()
        local req = CertificateService.ImportCertReq.new(CertificateUsageType, Type, Content, Id):validate()
        local obj = self:GetCertificateServiceCertificateServiceObject()

        return CertificateService.ImportCertRsp.new(obj:ImportCert(ctx, req:unpack(true)))
    end)
end

---@param CertificateUsageType CertificateService.CertificateUsageType
---@param Type string
---@param Content string
---@param Key string
---@return CertificateService.ImportCertWithKeyRsp
function spdm_client:CertificateServiceCertificateServiceImportCertWithKey(ctx, CertificateUsageType, Type, Content, Key)
    local req = CertificateService.ImportCertWithKeyReq.new(CertificateUsageType, Type, Content, Key):validate()
    local obj = self:GetCertificateServiceCertificateServiceObject()

    return CertificateService.ImportCertWithKeyRsp.new(obj:ImportCertWithKey(ctx, req:unpack(true)))
end

function spdm_client:PCertificateServiceCertificateServiceImportCertWithKey(ctx, CertificateUsageType, Type, Content,
    Key)
    return pcall(function()
        local req = CertificateService.ImportCertWithKeyReq.new(CertificateUsageType, Type, Content, Key):validate()
        local obj = self:GetCertificateServiceCertificateServiceObject()

        return CertificateService.ImportCertWithKeyRsp.new(obj:ImportCertWithKey(ctx, req:unpack(true)))
    end)
end

---@param CertificateUsageType CertificateService.CertificateUsageType
---@param Type string
---@param Content string
---@param Id integer
---@param WithEncryptedKey boolean
---@param Password string
---@param Extra CertificateService.Extra
---@return CertificateService.ImportCertificateRsp
function spdm_client:CertificateServiceCertificateServiceImportCertificate(ctx, CertificateUsageType, Type, Content, Id,
    WithEncryptedKey, Password, Extra)
    local req = CertificateService.ImportCertificateReq.new(CertificateUsageType, Type, Content, Id, WithEncryptedKey,
        Password, Extra):validate()
    local obj = self:GetCertificateServiceCertificateServiceObject()

    return CertificateService.ImportCertificateRsp.new(obj:ImportCertificate(ctx, req:unpack(true)))
end

function spdm_client:PCertificateServiceCertificateServiceImportCertificate(ctx, CertificateUsageType, Type, Content,
    Id, WithEncryptedKey, Password, Extra)
    return pcall(function()
        local req = CertificateService.ImportCertificateReq.new(CertificateUsageType, Type, Content, Id,
            WithEncryptedKey, Password, Extra):validate()
        local obj = self:GetCertificateServiceCertificateServiceObject()

        return CertificateService.ImportCertificateRsp.new(obj:ImportCertificate(ctx, req:unpack(true)))
    end)
end

---@param Country string
---@param State string
---@param Location string
---@param OrgName string
---@param OrgUnit string
---@param CommonName string
---@param AlternativeNames string[]
---@return CertificateService.StartGenerateCSRRsp
function spdm_client:CertificateServiceCertificateServiceStartGenerateCSR(ctx, Country, State, Location, OrgName,
    OrgUnit, CommonName, AlternativeNames)
    local req = CertificateService.StartGenerateCSRReq.new(Country, State, Location, OrgName, OrgUnit, CommonName,
        AlternativeNames):validate()
    local obj = self:GetCertificateServiceCertificateServiceObject()

    return CertificateService.StartGenerateCSRRsp.new(obj:StartGenerateCSR(ctx, req:unpack(true)))
end

function spdm_client:PCertificateServiceCertificateServiceStartGenerateCSR(ctx, Country, State, Location, OrgName,
    OrgUnit, CommonName, AlternativeNames)
    return pcall(function()
        local req = CertificateService.StartGenerateCSRReq.new(Country, State, Location, OrgName, OrgUnit, CommonName,
            AlternativeNames):validate()
        local obj = self:GetCertificateServiceCertificateServiceObject()

        return CertificateService.StartGenerateCSRRsp.new(obj:StartGenerateCSR(ctx, req:unpack(true)))
    end)
end

---@param Country string
---@param State string
---@param Location string
---@param OrgName string
---@param OrgUnit string
---@param CommonName string
---@param AlternativeNames string[]
---@param KeyUsage string[]
---@param KeyBitLength integer
---@param Options CertificateService.CSRProperty
---@return CertificateService.GenerateCSRRsp
function spdm_client:CertificateServiceCertificateServiceGenerateCSR(ctx, Country, State, Location, OrgName, OrgUnit,
    CommonName, AlternativeNames, KeyUsage, KeyBitLength, Options)
    local req = CertificateService.GenerateCSRReq.new(Country, State, Location, OrgName, OrgUnit, CommonName,
        AlternativeNames, KeyUsage, KeyBitLength, Options):validate()
    local obj = self:GetCertificateServiceCertificateServiceObject()

    return CertificateService.GenerateCSRRsp.new(obj:GenerateCSR(ctx, req:unpack(true)))
end

function spdm_client:PCertificateServiceCertificateServiceGenerateCSR(ctx, Country, State, Location, OrgName, OrgUnit,
    CommonName, AlternativeNames, KeyUsage, KeyBitLength, Options)
    return pcall(function()
        local req = CertificateService.GenerateCSRReq.new(Country, State, Location, OrgName, OrgUnit, CommonName,
            AlternativeNames, KeyUsage, KeyBitLength, Options):validate()
        local obj = self:GetCertificateServiceCertificateServiceObject()

        return CertificateService.GenerateCSRRsp.new(obj:GenerateCSR(ctx, req:unpack(true)))
    end)
end

---@param Path string
---@return CertificateService.ExportCSRRsp
function spdm_client:CertificateServiceCertificateServiceExportCSR(ctx, Path)
    local req = CertificateService.ExportCSRReq.new(Path):validate()
    local obj = self:GetCertificateServiceCertificateServiceObject()

    return CertificateService.ExportCSRRsp.new(obj:ExportCSR(ctx, req:unpack(true)))
end

function spdm_client:PCertificateServiceCertificateServiceExportCSR(ctx, Path)
    return pcall(function()
        local req = CertificateService.ExportCSRReq.new(Path):validate()
        local obj = self:GetCertificateServiceCertificateServiceObject()

        return CertificateService.ExportCSRRsp.new(obj:ExportCSR(ctx, req:unpack(true)))
    end)
end

---@param CertificateUsageType CertificateService.CertificateUsageType
---@return CertificateService.ExportCertKeyByFIFORsp
function spdm_client:CertificateServiceCertificateServiceExportCertKeyByFIFO(ctx, CertificateUsageType)
    local req = CertificateService.ExportCertKeyByFIFOReq.new(CertificateUsageType):validate()
    local obj = self:GetCertificateServiceCertificateServiceObject()

    return CertificateService.ExportCertKeyByFIFORsp.new(obj:ExportCertKeyByFIFO(ctx, req:unpack(true)))
end

function spdm_client:PCertificateServiceCertificateServiceExportCertKeyByFIFO(ctx, CertificateUsageType)
    return pcall(function()
        local req = CertificateService.ExportCertKeyByFIFOReq.new(CertificateUsageType):validate()
        local obj = self:GetCertificateServiceCertificateServiceObject()

        return CertificateService.ExportCertKeyByFIFORsp.new(obj:ExportCertKeyByFIFO(ctx, req:unpack(true)))
    end)
end

---@param CertificateUsageType CertificateService.CertificateUsageType
---@param Id integer
---@return CertificateService.DeleteCertRsp
function spdm_client:CertificateServiceCertificateServiceDeleteCert(ctx, CertificateUsageType, Id)
    local req = CertificateService.DeleteCertReq.new(CertificateUsageType, Id):validate()
    local obj = self:GetCertificateServiceCertificateServiceObject()

    return CertificateService.DeleteCertRsp.new(obj:DeleteCert(ctx, req:unpack(true)))
end

function spdm_client:PCertificateServiceCertificateServiceDeleteCert(ctx, CertificateUsageType, Id)
    return pcall(function()
        local req = CertificateService.DeleteCertReq.new(CertificateUsageType, Id):validate()
        local obj = self:GetCertificateServiceCertificateServiceObject()

        return CertificateService.DeleteCertRsp.new(obj:DeleteCert(ctx, req:unpack(true)))
    end)
end

---@param CertificateUsageType CertificateService.CertificateUsageType
---@param Id integer
---@return CertificateService.GetCertChainInfoRsp
function spdm_client:CertificateServiceCertificateServiceGetCertChainInfo(ctx, CertificateUsageType, Id)
    local req = CertificateService.GetCertChainInfoReq.new(CertificateUsageType, Id):validate()
    local obj = self:GetCertificateServiceCertificateServiceObject()

    return CertificateService.GetCertChainInfoRsp.new(obj:GetCertChainInfo(ctx, req:unpack(true)))
end

function spdm_client:PCertificateServiceCertificateServiceGetCertChainInfo(ctx, CertificateUsageType, Id)
    return pcall(function()
        local req = CertificateService.GetCertChainInfoReq.new(CertificateUsageType, Id):validate()
        local obj = self:GetCertificateServiceCertificateServiceObject()

        return CertificateService.GetCertChainInfoRsp.new(obj:GetCertChainInfo(ctx, req:unpack(true)))
    end)
end

---@param Country string
---@param CommonName string
---@param OrgName string
---@return CertificateService.SetDefaultSSLCertSubjectRsp
function spdm_client:CertificateServiceCertificateServiceSetDefaultSSLCertSubject(ctx, Country, CommonName, OrgName)
    local req = CertificateService.SetDefaultSSLCertSubjectReq.new(Country, CommonName, OrgName):validate()
    local obj = self:GetCertificateServiceCertificateServiceObject()

    return CertificateService.SetDefaultSSLCertSubjectRsp.new(obj:SetDefaultSSLCertSubject(ctx, req:unpack(true)))
end

function spdm_client:PCertificateServiceCertificateServiceSetDefaultSSLCertSubject(ctx, Country, CommonName, OrgName)
    return pcall(function()
        local req = CertificateService.SetDefaultSSLCertSubjectReq.new(Country, CommonName, OrgName):validate()
        local obj = self:GetCertificateServiceCertificateServiceObject()

        return CertificateService.SetDefaultSSLCertSubjectRsp.new(obj:SetDefaultSSLCertSubject(ctx, req:unpack(true)))
    end)
end

---@param Type string
---@param Content string
---@param CertId integer
---@return CertificateService.ImportCRLRsp
function spdm_client:CertificateServiceCertificateServiceImportCRL(ctx, Type, Content, CertId)
    local req = CertificateService.ImportCRLReq.new(Type, Content, CertId):validate()
    local obj = self:GetCertificateServiceCertificateServiceObject()

    return CertificateService.ImportCRLRsp.new(obj:ImportCRL(ctx, req:unpack(true)))
end

function spdm_client:PCertificateServiceCertificateServiceImportCRL(ctx, Type, Content, CertId)
    return pcall(function()
        local req = CertificateService.ImportCRLReq.new(Type, Content, CertId):validate()
        local obj = self:GetCertificateServiceCertificateServiceObject()

        return CertificateService.ImportCRLRsp.new(obj:ImportCRL(ctx, req:unpack(true)))
    end)
end

---@return CertificateService.GetCSRContentRsp
function spdm_client:CertificateServiceCertificateServiceGetCSRContent(ctx)
    local obj = self:GetCertificateServiceCertificateServiceObject()

    return CertificateService.GetCSRContentRsp.new(obj:GetCSRContent(ctx))
end

function spdm_client:PCertificateServiceCertificateServiceGetCSRContent(ctx)
    return pcall(function()
        local obj = self:GetCertificateServiceCertificateServiceObject()

        return CertificateService.GetCSRContentRsp.new(obj:GetCSRContent(ctx))
    end)
end

---@param Property string
---@return CertificateService.GetCSRPropertyRsp
function spdm_client:CertificateServiceCertificateServiceGetCSRProperty(ctx, Property)
    local req = CertificateService.GetCSRPropertyReq.new(Property):validate()
    local obj = self:GetCertificateServiceCertificateServiceObject()

    return CertificateService.GetCSRPropertyRsp.new(obj:GetCSRProperty(ctx, req:unpack(true)))
end

function spdm_client:PCertificateServiceCertificateServiceGetCSRProperty(ctx, Property)
    return pcall(function()
        local req = CertificateService.GetCSRPropertyReq.new(Property):validate()
        local obj = self:GetCertificateServiceCertificateServiceObject()

        return CertificateService.GetCSRPropertyRsp.new(obj:GetCSRProperty(ctx, req:unpack(true)))
    end)
end

---@param Property CertificateService.CSRProperty
---@return CertificateService.SetCSRPropertyRsp
function spdm_client:CertificateServiceCertificateServiceSetCSRProperty(ctx, Property)
    local req = CertificateService.SetCSRPropertyReq.new(Property):validate()
    local obj = self:GetCertificateServiceCertificateServiceObject()

    return CertificateService.SetCSRPropertyRsp.new(obj:SetCSRProperty(ctx, req:unpack(true)))
end

function spdm_client:PCertificateServiceCertificateServiceSetCSRProperty(ctx, Property)
    return pcall(function()
        local req = CertificateService.SetCSRPropertyReq.new(Property):validate()
        local obj = self:GetCertificateServiceCertificateServiceObject()

        return CertificateService.SetCSRPropertyRsp.new(obj:SetCSRProperty(ctx, req:unpack(true)))
    end)
end

---@param Usage string
---@param Certificates string[]
---@return CertificateService.BackupCertificateRsp
function spdm_client:CertificateServiceCertificateServiceBackupCertificate(ctx, Usage, Certificates)
    local req = CertificateService.BackupCertificateReq.new(Usage, Certificates):validate()
    local obj = self:GetCertificateServiceCertificateServiceObject()

    return CertificateService.BackupCertificateRsp.new(obj:BackupCertificate(ctx, req:unpack(true)))
end

function spdm_client:PCertificateServiceCertificateServiceBackupCertificate(ctx, Usage, Certificates)
    return pcall(function()
        local req = CertificateService.BackupCertificateReq.new(Usage, Certificates):validate()
        local obj = self:GetCertificateServiceCertificateServiceObject()

        return CertificateService.BackupCertificateRsp.new(obj:BackupCertificate(ctx, req:unpack(true)))
    end)
end

function spdm_client:ctor()
    self.signal_slots = {}
end

---@type spdm_client
return spdm_client.new('spdm')
